package validators

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"unicode/utf8"

	"github.com/thedevsaddam/govalidator"

	"github.com/runningwater/gohub/pkg/database"
)

func init() {
	// 自定义验证规则 not_exists, 用于验证数据不存在于数据库中
	// 常用于保证数据库某个字段的值唯一， 如用户名、邮箱、手机号或者分类的名称
	//
	// 用法示例
	//
	// 规则： not_exists:users,phone
	// 解释：验证 users 表中是否存在 phone 字段的值，phone 为待验证的值
	//
	// 规则： not_exists:users,phone,10
	// 解释：验证 users 表中是否存在 phone 字段的值，同时排除 id 为 10 的记录
	govalidator.AddCustomRule("not_exists", func(field string, rule string, message string, value any) error {
		rng := strings.Split(strings.TrimPrefix(rule, "not_exists:"), ",")

		// 第一个参数，表名称，如 users
		tableName := rng[0]
		// 第二个参数，字段名称，如 phone
		fieldName := rng[1]
		// 第三个参数，排除 ID
		var exceptID string
		if len(rng) > 2 {
			exceptID = rng[2]
		}

		// 用户请求的值
		requestValue := value.(string)

		// 调用数据库查询方法，检查数据是否存在
		query := database.DB.Table(tableName).Where(fieldName+" = ?", requestValue)
		if len(exceptID) > 0 {
			query.Where("id != ?", exceptID)
		}
		var count int64
		query.Count(&count)

		// 如果 count 大于 0，表示数据已存在，返回错误信息
		if count > 0 {
			// 如果有自定义错误消息的话，使用自定义错误消息
			if len(message) > 0 {
				return errors.New(message)
			}
			return fmt.Errorf("%v 已存在", requestValue)
		}

		return nil

	})

	// max_cn:8 中文最多 8 个字
	govalidator.AddCustomRule("max_cn", func(field string, rule string, message string, value any) error {
		valueLen := utf8.RuneCountInString(value.(string))
		maxLen, _ := strconv.Atoi(strings.TrimPrefix(rule, "max_cn:"))
		if valueLen > maxLen {
			// 如果有自定义错误消息的话，使用自定义消息
			if message != "" {
				return errors.New(message)
			}
			return fmt.Errorf("%v 长度不能超过 %v 个字", field, maxLen)
		}
		return nil
	})

	// min_cn:8 中文长度最少 8 个字
	govalidator.AddCustomRule("min_cn", func(field string, rule string, message string, value any) error {
		valueLen := utf8.RuneCountInString(value.(string))
		minLen, _ := strconv.Atoi(strings.TrimPrefix(rule, "min_cn:"))
		if valueLen < minLen {
			// 如果有自定义错误消息的话，使用自定义消息
			if message != "" {
				return errors.New(message)
			}
			return fmt.Errorf("%v 长度不能小于 %v 个字", field, minLen)
		}
		return nil
	})

	// 自定义规则 exists, 确保数据库存在某条数据
	// exists:categories,id
	govalidator.AddCustomRule("exists", func(field string, rule string, message string, value any) error {
		rng := strings.Split(strings.TrimPrefix(rule, "exists:"), ",")

		// 第一个参数，表名称，如 categories
		tableName := rng[0]
		// 第二个参数，字段名称，如 id
		fieldName := rng[1]

		// 用户请求的值
		requestValue := value.(string)

		// 调用数据库查询方法，检查数据是否存在
		var count int64
		database.DB.Table(tableName).Where(fieldName+" = ?", requestValue).Count(&count)

		// 如果 count 小于等于 0，表示数据不存在，返回错误信息
		if count <= 0 {
			// 如果有自定义错误消息的话，使用自定义消息
			if message != "" {
				return errors.New(message)
			}
			return fmt.Errorf("%v 不存在", requestValue)
		}

		return nil
	})
}
